# 1. git reset 三种模式

git reset --hard指的是恢复某一个库。git reset --hard HEAD^ 是向前回退版本,其中HEAD后面跟几个^ 就是往回退几个版本,如果回退100个版本,可以写成 HEAD~100

git reset有三种模式,soft,mixed,hard,具体的使用方法下面这张图,展示的很全面了。

img

# 1.1. git reset 语法

命令格式:git reset [--soft | --mixed | --hard] [<commit>]

# 1.1.1. 使用参数--hard,如git reset --hard

  1. 替换引用的指向。引用指向新的提交ID。

  2. 替换暂存区。替换后,暂存区的内容和引用指向的目录树一致

  3. 替换工作区。替换后,工作区的内容变得和暂存区一致,也和HEAD所指向的目录树内容相同

# 1.1.2. 使用参数--soft,如 git reset --soft

即只更改引用的指向,不改变暂存区和工作区

只改变commit(指针指向),stage index 和 working directory 不变

# 1.1.3. 使用参数--mixed或者不使用参数(默认为--mixed),如 git reset

更改引用的指向及重置暂存区,但是不改变工作区

只改变commit(指针指向) 和 add (stage index),working directory不变

# 1.2. git reset 原理

# 1.2.1. --hard

重置位置的同时,直接将 working Tree工作目录、 index 暂存区及repository 都重置成目标Reset节点的內容,所以效果看起来等同于清空暂存区和工作区。

# 1.2.2. --soft

重置位置的同时,保留working Tree工作目录和index暂存区的内容,只让repository中的内容和 reset 目标节点保持一致,因此原节点和reset节点之间的【差异变更集】会放入index暂存区中(Staged files)。 所以效果看起来就是工作目录的内容不变,暂存区原有的内容也不变,只是原节点和Reset节点之间的所有差异都会放到暂存区中。

# 1.2.3. --mixed(默认)

重置位置的同时,只保留Working Tree工作目录的內容,但会将 Index暂存区 和 Repository 中的內容更改和reset目标节点一致,因此原节点和Reset节点之间的【差异变更集】会放入Working Tree工作目录中。 所以效果看起来就是原节点和Reset节点之间的所有差异都会放到工作目录中。

# 1.3. 总结

reset 的本质:移动 HEAD 以及它所指向的 branch

实质上,reset 这个指令虽然可以用来撤销 commit ,但它的实质行为并不是撤销,而是移动 HEAD ,并且「捎带」上 HEAD 所指向的 branch(如果有的话)。也就是说,reset 这个指令的行为其实和它的字面意思 "reset"(重置)十分相符:它是用来重置 HEAD 以及它所指向的 branch 的位置的。

reset --hard HEAD^ 之所以起到了撤销 commit 的效果,是因为它把 HEAD 和它所指向的 branch 一起移动到了当前 commit 的父 commit 上,从而起到了「撤销」的效果:

img

Git 的历史只能往回看,不能向未来看,所以把 HEADbranch 往回移动,就能起到撤回 commit 的效果。

所以同理,reset --hard 不仅可以撤销提交,还可以用来把 HEADbranch 移动到其他的任何地方。

git reset --hard branch2

img